#include "resourceManager.h"

FileInfo::FileInfo(unsigned int fileId,unsigned int fileLen){
	_fileLen = fileLen;
	_fileId = fileId;
	_oldCount = _newCount = 0;
	pthread_mutex_init(&count_mutex,NULL);
}

int
FileInfo::addNewRS(unsigned int rsId){
	vector<unsigned int > ::iterator it;
	pthread_mutex_lock(&count_mutex);
	for(it = _rsset.begin();it!= _rsset.end();it++){
	//	cout<<*it<<" "<<rsId<<endl;
		if(*it == rsId){
//			cout<<"rs "<<rsId<<" already have this file!"<<endl;
			pthread_mutex_unlock(&count_mutex);
			return -1;
		}
	}
	_rsset.push_back(rsId);
	pthread_mutex_unlock(&count_mutex);
	return 0;
}

int
FileInfo::deleteRS(unsigned int rsId){
	vector<unsigned int > ::iterator it;
	pthread_mutex_lock(&count_mutex);
	for(it = _rsset.begin();it!= _rsset.end();it++){
		if(*it == rsId){
			_rsset.erase(it);
			pthread_mutex_unlock(&count_mutex);
			return 0;
		}
	}
	cout<<"can't find rs "<<rsId<<endl;
	pthread_mutex_unlock(&count_mutex);
	return -1;
	
}

int
FileInfo::getRSSet(vector<unsigned int > & rsset){
	int result;
	vector<unsigned int>::iterator it;
	pthread_mutex_lock(&count_mutex);
	if(_rsset.size() ==0)
		result = -1;
	else{
		for(it = _rsset.begin();it!= _rsset.end();it++){
			rsset.push_back(*it);
		}
		result = 0;
	}
	pthread_mutex_unlock(&count_mutex);
	return result;
}

unsigned int
FileInfo::getTotalCount(){
	unsigned int result;
	pthread_mutex_lock(&count_mutex);
	result = _oldCount + _newCount;
	pthread_mutex_unlock(&count_mutex);
	return result;
}

void
FileInfo::resetCount(){
	pthread_mutex_lock(&count_mutex);
	_oldCount = _newCount = 0;
	pthread_mutex_unlock(&count_mutex);
}

unsigned int 
FileInfo::getFileId(){
	return _fileId;
}

unsigned int
FileInfo::getFileLen(){
	return _fileLen;
}

void
FileInfo::visited(){
	pthread_mutex_lock(&count_mutex);
	_newCount ++;
	pthread_mutex_unlock(&count_mutex);
}



ResourceManager::ResourceManager(LBServer *lb,unsigned int resourceNumber,unsigned int maxFileLen,unsigned int minFileLen){
	_lb = lb;
	_resourceNumber = (resourceNumber);
	_maxFileLen=(maxFileLen);
	_minFileLen=(minFileLen);
	
}

void 
ResourceManager::initialLayOut(unsigned int rsNumber,unsigned int copys ){
	unsigned fileLen,rsId;
	FileInfo *newfile;
	for(unsigned int i= 0;i< _resourceNumber ;i++){
		fileLen = Randomi(_minFileLen,_maxFileLen);
		newfile = new FileInfo(i,fileLen);
		_fileList.push_back(newfile);
		//create copys;
		rsId = Randomi(0,rsNumber);
		for(unsigned int j = 0;j<copys;j++){
			rsId = (rsId + j)%rsNumber;
			if(addNewRS(i,rsId) == 0){
				cout<<"add file "<<i <<" to rs "<<rsId<<endl;
				_lb->addNewFile(rsId,i);
			}else{
				exit(1);
				j--;
			}
		}
	}
}

void 
ResourceManager::resetCount(unsigned int fileId){
	if(fileId >= _fileList.size()){
		cout<<"wrong fileId"<<endl;
		exit(1);
	}
	_fileList[fileId]->resetCount();
//	cout<<"reset the count of file "<<fileId<<endl;
}

unsigned int 
ResourceManager::getFileLen(unsigned int fileId){
	return _fileList[fileId]->getFileLen();
}

void
ResourceManager::visited(unsigned int fileId){
	_fileList[fileId]->visited();
}

int
ResourceManager::addNewRS(unsigned int fileId,unsigned int rsId){
	return _fileList[fileId]->addNewRS(rsId);
}

int
ResourceManager::deleteRS(unsigned int fileId,unsigned int rsId){
	return _fileList[fileId]->deleteRS(rsId);
}

int
ResourceManager::getRSSet(unsigned int fileId,vector<unsigned int> &rsset){
	if(_fileList.size() <= fileId){
		cout<<"wrong fileId,and size = "<<_fileList.size()<<",fileId = "<<fileId<<endl;
		exit(1);
	}
	return _fileList[fileId]->getRSSet(rsset);
}

unsigned int 
ResourceManager::findMaxCountFile(vector<bool> &canChooseFile){
	unsigned int currentCount,maxCount  =0;
	unsigned int resultRs = 0;
	for(unsigned int i =0;i<_resourceNumber;i++){
		if(canChooseFile[i] == false){
//			cout<<"file "<<i<<" can't be chosed"<<endl;
			continue;
		}
		currentCount= _fileList[i]->getTotalCount();
		if(currentCount > maxCount){
			maxCount = currentCount;
			resultRs = i;
		}
//		cout<<"fileId = "<<i<<",currentCount = "<<currentCount<<",maxCount = "<<maxCount<<endl;
	}
	return resultRs;
}

unsigned int
ResourceManager::findBestDest(unsigned int rsId,unsigned int spreadFileId){
	return 0;
}
